Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit e60cf538ab3bd3f5e24b1c42da29e062492e4ce6


Parents : 81df343
Author : Mark Qvist <bc7291552be7a58f361522990465165c>
Signature : T66BB85Valid, signed by author
Date : 2026-06-27T23:32:18+02:00

Fixed log viewer not copying service log on Android

Changes

4 files changed, 49 insertions(+), 15 deletions(-)

M sbapp/main.py +5 -2

Diff

diff --git a/sbapp/main.py b/sbapp/main.py
index dabf9177..2a3617da 100644
--- a/sbapp/main.py
+++ b/sbapp/main.py
@@ -3865,6 +3865,7 @@ class SidebandApp(MDApp):
self.widget_hide(self.connectivity_screen.ids.connectivity_modem_fields)
self.widget_hide(self.connectivity_screen.ids.connectivity_transport_label)
self.widget_hide(self.connectivity_screen.ids.connectivity_enable_transport)
+ self.widget_hide(self.connectivity_screen.ids.connectivity_obfuscate_hops)
self.widget_hide(self.connectivity_screen.ids.connectivity_serial_label)
self.widget_hide(self.connectivity_screen.ids.connectivity_use_serial)
self.widget_hide(self.connectivity_screen.ids.connectivity_use_weave)
@@ -3873,8 +3874,6 @@ class SidebandApp(MDApp):
self.widget_hide(self.connectivity_screen.ids.connectivity_shared_access)
self.widget_hide(self.connectivity_screen.ids.connectivity_shared_access_label)
self.widget_hide(self.connectivity_screen.ids.connectivity_shared_access_fields)
- self.widget_hide(self.connectivity_screen.ids.connectivity_transport_label)
- self.widget_hide(self.connectivity_screen.ids.connectivity_enable_transport)
self.widget_hide(self.connectivity_screen.ids.connectivity_transport_info)
self.widget_hide(self.connectivity_screen.ids.connectivity_transport_fields)
self.widget_hide(self.connectivity_screen.ids.connectivity_service_restart_fields)
@@ -3917,6 +3916,7 @@ class SidebandApp(MDApp):
def save_connectivity(sender=None, event=None):
self.sideband.config["connect_transport"] = self.connectivity_screen.ids.connectivity_enable_transport.active
+ self.sideband.config["connect_obfuscate_hops"] = self.connectivity_screen.ids.connectivity_obfuscate_hops.active
self.sideband.config["connect_share_instance"] = self.connectivity_screen.ids.connectivity_share_instance.active
self.sideband.config["connect_local"] = self.connectivity_screen.ids.connectivity_use_local.active
self.sideband.config["connect_local_groupid"] = self.connectivity_screen.ids.connectivity_local_groupid.text
@@ -4089,6 +4089,9 @@ class SidebandApp(MDApp):
con_collapse_transport(collapse=not self.sideband.config["connect_transport"])
self.connectivity_screen.ids.connectivity_enable_transport.bind(active=save_connectivity)
+ self.connectivity_screen.ids.connectivity_obfuscate_hops.active = self.sideband.config["connect_obfuscate_hops"]
+ self.connectivity_screen.ids.connectivity_obfuscate_hops.bind(active=save_connectivity)
+
self.connectivity_screen.ids.connectivity_share_instance.active = self.sideband.config["connect_share_instance"]
self.connectivity_screen.ids.connectivity_share_instance.bind(active=save_connectivity)

diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py
index 1883d9d3..d71133c9 100644
--- a/sbapp/sideband/core.py
+++ b/sbapp/sideband/core.py
@@ -351,13 +351,23 @@ class SidebandCore():
if not os.path.isdir(self.rns_configdir):
os.makedirs(self.rns_configdir)
+ generated_config = self.config_template
RNS.log("Configuring Reticulum instance...")
if self.config["connect_transport"]:
RNS.log("Enabling Reticulum Transport")
- generated_config = self.config_template.replace("TRANSPORT_IS_ENABLED", "Yes")
+ generated_config = generated_config.replace("TRANSPORT_IS_ENABLED", "Yes")
else:
RNS.log("Not enabling Reticulum Transport")
- generated_config = self.config_template.replace("TRANSPORT_IS_ENABLED", "No")
+ generated_config = generated_config.replace("TRANSPORT_IS_ENABLED", "No")
+
+ if self.config["connect_obfuscate_hops"]:
+ RNS.log("Enabling hop-count obfuscation")
+ generated_config = generated_config.replace("LOCAL_HOPS_DELTA", "Yes")
+ if self.is_service and not "local_hops_delta = LOCAL_HOPS_DELTA" in self.config_template:
+ self.setstate("hardware_operation.error", "Hop-count obfuscation was enabled in connectivity settings, but the \"local_hops_delta = LOCAL_HOPS_DELTA\" line was not found in the configuration template. This probably means that you're using an edited template, which does not include the required line. Hop count obfuscation will not take effect until it is restored.")
+ else:
+ RNS.log("Not enabling hop-count obfuscation")
+ generated_config = generated_config.replace("LOCAL_HOPS_DELTA", "No")
config_file = open(os.path.join(self.rns_configdir, "config"), "wb")
config_file.write(generated_config.encode("utf-8"))
@@ -544,6 +554,7 @@ class SidebandCore():
self.config["connect_ifmode_modem"] = "full"
self.config["connect_ifmode_serial"] = "full"
self.config["connect_ifmode_bluetooth"] = "full"
+ self.config["connect_obfuscate_hops"] = False
# Hardware
self.config["hw_rnode_frequency"] = None
@@ -679,6 +690,7 @@ class SidebandCore():
if not "config_template" in self.config: self.config["config_template"] = None
if not "connect_transport" in self.config: self.config["connect_transport"] = False
+ if not "connect_obfuscate_hops" in self.config: self.config["connect_obfuscate_hops"] = False
if not "connect_share_instance" in self.config: self.config["connect_share_instance"] = False
if not "connect_rnode" in self.config: self.config["connect_rnode"] = False
if not "connect_rnode_ifac_netname" in self.config: self.config["connect_rnode_ifac_netname"] = ""
@@ -4813,8 +4825,7 @@ class SidebandCore():
self.message_router.handle_outbound(lxm)
- if not no_display:
- self.lxm_ingest(lxm, originator=True)
+ if not no_display: self.lxm_ingest(lxm, originator=True)
return True
@@ -4978,8 +4989,7 @@ class SidebandCore():
RNS.log("Message does not exist, saving", RNS.LOG_DEBUG)
self._db_save_lxm(message, context_dest, originator, own_command=own_command)
- if is_trusted:
- should_notify = True
+ if is_trusted: should_notify = True
if len(message.content) == 0 and len(message.title) == 0:
if (LXMF.FIELD_TELEMETRY in message.fields or LXMF.FIELD_TELEMETRY_STREAM in message.fields or LXMF.FIELD_COMMANDS in message.fields):
@@ -5541,10 +5551,12 @@ rns_config = """# This template is used to generate a
# will be reset to this default.
[reticulum]
- # Don't change this line, use the UI
- # setting for selecting whether RNS
- # transport is enabled or disabled
+ # Don't change these lines, use the UI
+ # settings instead. Removing them from
+ # the config template will break these
+ # settings controls in the UI.
enable_transport = TRANSPORT_IS_ENABLED
+ local_hops_delta = LOCAL_HOPS_DELTA
# Changing this setting will cause
# Sideband to not work.

diff --git a/sbapp/ui/layouts.py b/sbapp/ui/layouts.py
index 7faf7a45..efdfeb58 100644
--- a/sbapp/ui/layouts.py
+++ b/sbapp/ui/layouts.py
@@ -750,6 +750,24 @@ MDScreen:
size_hint_y: None
height: dp(24)
+ MDLabel:
+ id: connectivity_obfuscate_hops_label
+ text: "Obfuscate Hop Counts"
+ font_style: "H6"
+ # disabled: True
+
+ MDSwitch:
+ id: connectivity_obfuscate_hops
+ active: False
+ pos_hint: {"center_y": 0.3}
+ # disabled: True
+
+ MDBoxLayout:
+ orientation: "horizontal"
+ padding: [0,dp(12),dp(24),0]
+ size_hint_y: None
+ height: dp(36)
+
MDLabel:
id: connectivity_transport_label
text: "Enable Reticulum Transport"

diff --git a/sbapp/ui/utilities.py b/sbapp/ui/utilities.py
index aa8da1bd..597e4660 100644
--- a/sbapp/ui/utilities.py
+++ b/sbapp/ui/utilities.py
@@ -196,18 +196,19 @@ class Utilities():
except Exception as e: service_output = f"An error occurred while retrieving log entries:\n{e}"
- self.logviewer_screen.log_contents = output
+ if not RNS.vendor.platformutils.is_android(): self.logviewer_screen.log_contents = output
+ else: self.logviewer_screen.log_contents = f"# Frontend Log\n\n{output}\n\n# Service Log\n\n{service_output}"
+
def cb(dt):
if not RNS.vendor.platformutils.is_android():
self.logviewer_screen.ids.logviewer_output.text = f"[font=RobotoMono-Regular][size={int(dp(12))}]{output}[/size][/font]"
else:
self.logviewer_screen.ids.logviewer_output.text = f"[size=18dp][b]Frontend Log[/b][/size][size=5dp]\n \n[font=RobotoMono-Regular][size={int(dp(12))}]{output}[/size][/font]"
self.logviewer_screen.ids.slogviewer_output.text = f"\n[size=18dp][b]Service Log[/b][/size][size=5dp]\n \n[font=RobotoMono-Regular][size={int(dp(12))}]{service_output}[/size][/font]"
- self.logviewer_screen.log_contents += f"\n\n{service_output}"
+
Clock.schedule_once(cb, 0.2)
- if self.app.root.ids.screen_manager.current == "logviewer_screen":
- Clock.schedule_once(self.update_logviewer, 1)
+ if self.app.root.ids.screen_manager.current == "logviewer_screen": Clock.schedule_once(self.update_logviewer, 1)
def logviewer_copy(self, sender=None):
Clipboard.copy(self.logviewer_screen.log_contents)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────